package org.ykh.service.config;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.*;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

/**
 * @author ykh
 */
@Configuration
//@ConditionalOnClass,当RedisConnectionFactory在类路径存在时加载（不能直接用在@Bean方法上）
@ConditionalOnClass(RedisConnectionFactory.class)
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);

        // 创建JSON序列化工具
        ObjectMapper objectMapper = new ObjectMapper();
        //配置对java8时间api的支持
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);//序列化时不自动将时间转化为时间戳
        objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
        //反序列化时，不尝试设置时区（即使源数据无时区信息，也会根据解析器上下文设置）
        objectMapper.registerModule(new JavaTimeModule());//注册java8的时间模块

        //对象序列化时包括类型信息,便于反序列化，但是在非java系统中不适用
//         objectMapper = objectMapper.activateDefaultTyping(
//                 LaissezFaireSubTypeValidator.instance,//不进行任何验证，允许所有
//                 ObjectMapper.DefaultTyping.NON_FINAL,
//                 JsonTypeInfo.As.PROPERTY);

        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

        final GenericJackson2JsonRedisSerializer jsonRedisSerializer =
                new GenericJackson2JsonRedisSerializer(objectMapper);
        //GenericJackson2JsonRedisSerializer构造器默认有一个这个配置，作用是啥不知道。
        GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);

        // 设置Key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}
